﻿using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Rendering;
using Unity.Transforms;
using UnityEngine;
using Random = Unity.Mathematics.Random;

namespace MyTanks
{
    public partial struct MyTanksPrepareSystem : ISystem
    {
        [BurstCompile]
        public void OnCreate(ref SystemState state)
        {
            state.RequireForUpdate<MyTanksConfig>();
        }


        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            state.Enabled = false;
            var config = SystemAPI.GetSingleton<MyTanksConfig>();

            var random = new Random(123);

            // var query = SystemAPI.QueryBuilder().WithAll<URPMaterialPropertyBaseColor>().Build();


            var ecb = new EntityCommandBuffer(Allocator.Temp);

            var shellCount = config.tankCount * 20;
            var shellsHolder = state.EntityManager.CreateEntity(new[]
                { new ComponentType(typeof(ShellHolder), ComponentType.AccessMode.ReadOnly) });
            var shellBuffer = ecb.AddBuffer<ShellBufferComponent>(shellsHolder);
            shellBuffer.Length = shellCount;
            for (int i = 0; i < shellCount; i++)
            {
                shellBuffer[i] = new ShellBufferComponent()
                    { shell = state.EntityManager.Instantiate(config.shellPrefab) };
            }

            var explosionBuffer = ecb.AddBuffer<ShellExplosionBufferComponent>(shellsHolder);
            explosionBuffer.Length = shellCount;
            for (int i = 0; i < shellCount; i++)
            {
                explosionBuffer[i] = new ShellExplosionBufferComponent()
                    { shellExplosion = state.EntityManager.Instantiate(config.shellExplosionPrefab) };
            }

            var tanks_A = new NativeArray<Entity>(config.tankCount, Allocator.Temp);
            ecb.Instantiate(config.tankPrefab_A, tanks_A);
            var tanks_B = new NativeArray<Entity>(config.tankCount, Allocator.Temp);
            ecb.Instantiate(config.tankPrefab_B, tanks_B);

            foreach (var tank in tanks_A)
            {
                ecb.AddComponent(tank, new Tank());
                ecb.AddComponent(tank, new TankTeamA());
                ecb.SetComponent(tank, new LocalTransform()
                {
                    Position = new float3(random.NextFloat(-50, 50), 1f, random.NextFloat(-50, 50)),
                    Rotation = quaternion.identity,
                    Scale = 1
                });
            }

            foreach (var tank in tanks_B)
            {
                ecb.AddComponent(tank, new Tank());
                ecb.AddComponent(tank, new TankTeamB());
                ecb.SetComponent(tank, new LocalTransform()
                {
                    Position = new float3(random.NextFloat(-50, 50), 1f, random.NextFloat(-50, 50)),
                    Rotation = quaternion.identity,
                    Scale = 1
                });
            }

            ecb.Playback(state.EntityManager);
        }


        // Helper to create any amount of colors as distinct from each other as possible.
        // See https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
        static float4 RandomColor(ref Random random)
        {
            // 0.618034005f is inverse of the golden ratio
            var hue = (random.NextFloat() + 0.618034005f) % 1;
            return (Vector4)Color.HSVToRGB(hue, 1.0f, 1.0f);
        }
    }

    public struct Tank : IComponentData
    {
    }

    public struct TankTeamA : IComponentData
    {
    }

    public struct TankTeamB : IComponentData
    {
    }

    [InternalBufferCapacity(0)]
    public struct ShellBufferComponent : IBufferElementData
    {
        public Entity shell;
    }

    [InternalBufferCapacity(0)]
    public struct ShellExplosionBufferComponent : IBufferElementData
    {
        public Entity shellExplosion;
    }

    public struct ShellHolder : IComponentData
    {
    }
}